package com.my.lucky.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.my.lucky.config.IwencaiConfig;
import com.my.lucky.entity.*;
import com.my.lucky.model.Gainian60Boll;
import com.my.lucky.model.Stock;
import com.my.lucky.model.Stock60Boll;
import com.my.lucky.repository.*;
import com.my.lucky.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Service
public class IWencaiServiceTools {
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
    private static final long DEFAULT_RANK = 0L;
    private static final int MAX_RECURSION_DAYS = 15;
    //  private final String IWENCAI_URL = "https://www.iwencai.com/customized/chart/get-robot-data";
    public volatile List<Map<String, Object>> cacheGainian = new ArrayList<>();

    @Autowired
    IwencaiConfig config;
    @Autowired
    StockHotRankRepository stockHotRankRepository;

    @Autowired
    Stock60BollService stock60BollService;

    @Autowired
    Gainian60BollService gainian60BollService;

    @Autowired
    StockLimitUpRepository stockLimitUpRepository;

    @Autowired
    StockLimitDownRepository stockLimitDownRepository;
    @Autowired
    IwencaiService icService;
    private String defKey;

    @Autowired
    private IwencaiConfig iwencaiConfig;
    @Autowired
    private SysInfoRepository sysInfoRepository;

    // 方法1：使用SimpleDateFormat传统方式
    public static String formatWithSimpleDateFormat(String template) {
        Date now = new Date();
        SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy年MM月dd日");
        SimpleDateFormat hourFormat = new SimpleDateFormat("yyyy年MM月dd日HH点");
        SimpleDateFormat minuteFormat = new SimpleDateFormat("yyyy年MM月dd日HH点mm分");

        return template
                .replace("{日}", dayFormat.format(now))
                .replace("{时}", hourFormat.format(now))
                .replace("{分}", minuteFormat.format(now));
    }

    public static void main(String[] args) {
        IWencaiServiceTools service = new IWencaiServiceTools();
        List<Stock> stockList = service.searchAllStocks("个股涨幅,昨天收盘价格,热度排行榜,昨天热度排行排名,所属概念,资金流向,主力资金流向,所属行业,换手率,成交量,RSI1值,RSI2值,RSI3值,boll中轨值,lower值,upper值,OBV值,MAOBV值,开盘价,最低价,最高价,60分钟boll中轨值,60分钟lower值,60分钟upper值", false);

    }

    /**
     * 获取指定天数前的个股热度排名
     *
     * @param stock JSON数据对象
     * @param days  回溯天数
     * @return 排名值，找不到时返回9999L
     */
    public static String getOldRank(JSONObject stock, int days) {
        if (stock == null) {
            return "";
        }

        // 参数校验
        Objects.requireNonNull(stock, "stock参数不能为null");
        if (days < 0) {
            throw new IllegalArgumentException("days不能为负数");
        }
        // 改为迭代实现避免递归问题
        while (days <= MAX_RECURSION_DAYS) {
            try {
                LocalDate date = LocalDate.now(ZoneId.of("Asia/Shanghai")).minusDays(days);
                String dateKey = "个股热度排名[" + date.format(DATE_FORMATTER) + "]";
                if (stock.getString(dateKey) != null) {
                    return stock.getString(dateKey);
                }
                days++; // 递增天数继续查找
            } catch (Exception e) {
                // 记录日志或处理异常
                break;
            }
        }
        return "0";
    }

    /**
     * 获取指定天数前的个股热度排名
     *
     * @param stock JSON数据对象
     * @param days  回溯天数
     * @return 排名值，找不到时返回9999L
     */
    public static String getOldGaiRank(JSONObject stock, int days) {
        if (stock == null) {
            return "";
        }

        // 参数校验
        Objects.requireNonNull(stock, "stock参数不能为null");
        if (days < 0) {
            throw new IllegalArgumentException("days不能为负数");
        }
        // 改为迭代实现避免递归问题
        while (days <= MAX_RECURSION_DAYS) {
            try {
                LocalDate date = LocalDate.now(ZoneId.of("Asia/Shanghai")).minusDays(days);
                String dateKey = "指数@板块热度排名名次[" + date.format(DATE_FORMATTER) + "]";
                if (stock.getString(dateKey) != null) {
                    return stock.getString(dateKey);
                }
                days++; // 递增天数继续查找
            } catch (Exception e) {
                // 记录日志或处理异常
                break;
            }
        }
        return "0";
    }

    /**
     * 处理万亿
     *
     * @param numberStr
     * @return
     */
    public static double convertToNumber(String numberStr) {
        // 检查字符串是否包含"万亿"后缀
        if (numberStr == null || numberStr.trim().isEmpty()) {
            return 0.0;
        }
        if (numberStr.contains("万亿")) {
            // 去除字符串中的"万亿"后缀
            String numStr = numberStr.replace("万亿", "");
            // 转换为数字并乘以10000（万亿转亿）
            return parseNumber(numStr) * 10000;
        } else {
            // 不包含万亿单位，直接转换为数字
            return parseNumber(numberStr) / 10000 / 10000;
        }
    }

    // 提取的解析数字的辅助方法
    private static double parseNumber(String numStr) {
        try {
            return Double.parseDouble(numStr);
        } catch (NumberFormatException e) {
            System.err.println("无法转换的数字格式: " + numStr);
            e.printStackTrace();
            return 0.0;
        }
    }

    // 提取的解析数字的辅助方法，保留2位小数
    private static double parseNumbers(String numStr) {
        try {
            if (numStr == null || numStr.trim().isEmpty()) {
                return 0.0;
            }
            double original = Double.parseDouble(numStr);
            // 四舍五入保留2位小数：先乘100取整，再除以100
            return Math.round(original * 100.0) / 100.0;
        } catch (NumberFormatException e) {
            System.err.println("无法转换的数字格式: " + numStr);
            e.printStackTrace();
            return 0.0;
        }
    }

    /**
     * 定时获取涨停数据的任务
     * 可以通过配置文件配置执行频率
     */
//    @Scheduled(cron = "${iwencai.limitup.interval:0 54 15 * * ?}") // 默认每天15点执行
    @Scheduled(cron = "${iwencai.limitup.interval:0 31,02 9-15 * * ?}") //9点到15点的 31分，02分执行
    public List<StockLimitUp> scheduleLimitUpTask() {
        List<StockLimitUp> limitUpStocks = new ArrayList<>();
        try {
            log.info("执行获取涨停数据任务.....");
            limitUpStocks = searchLimitUp("今日涨停的股票,热度排行榜,昨天热度排行排名,所属概念", config.getIsLocal());
            if (!limitUpStocks.isEmpty()) {
                stockLimitUpRepository.deleteByRecordTimeAfterToday();
                stockLimitUpRepository.saveAll(limitUpStocks);
                log.info("成功保存 {} 只涨停股票数据", limitUpStocks.size());
            } else {
                log.info("未获取到涨停股票数据");
            }
        } catch (Exception e) {
            log.error("执行涨停数据任务时发生异常", e);
        }
        return limitUpStocks;
    }

     /**
     * 定时获取跌停数据的任务
     * 可以通过配置文件配置执行频率
     */
//    @Scheduled(cron = "${iwencai.limitup.interval:0 54 15 * * ?}") // 默认每天15点执行
    @Scheduled(cron = "${iwencai.limitup.interval:0 31,55 9,10,11,14 * * ?}") //9点到15点的 31分，02分执行
    public List<StockLimitDown> scheduleLimitDownTask() {
        List<StockLimitDown> limitUpStocks = new ArrayList<>();
        try {
            log.info("执行获取涨停数据任务.....");
            limitUpStocks = searchLimitDown("今日跌停的股票,热度排行榜,昨天热度排行排名,所属概念", config.getIsLocal());
            if (!limitUpStocks.isEmpty()) {
                stockLimitDownRepository.deleteByRecordTimeAfterToday();
                stockLimitDownRepository.saveAll(limitUpStocks);
                log.info("成功保存 {} 只跌停股票数据", limitUpStocks.size());
            } else {
                log.info("未获取到跌停股票数据");
            }
        } catch (Exception e) {
            log.error("执行跌停数据任务时发生异常", e);
        }
        return limitUpStocks;
    }

//    @Scheduled(cron = "${iwencai.hot.interval}")
//    void schedule() {
//        try {
//            log.info("执行保存热度排行.....");
////            List<StockHotRank> stockHotRanks = searchHot();
////            stockHotRankRepository.saveAll(stockHotRanks);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }

    @PostConstruct
    @Scheduled(cron = "${iwencai.limitup.interval:0 31,02 9-22 * * ?}") //9点到15点的 31分，02分执行
    public void init() {
        System.out.printf("init()===");
        defKey = config.getGainianKeyword();
        List<SysInfo> sysInfos = sysInfoRepository.findAll();
        if (sysInfos != null && sysInfos.size() > 0) {
            List<SysInfo> checksysInfos = new ArrayList<>();
            SysInfo allcheck = new SysInfo();
            for (SysInfo info : sysInfos) {
                if ("focusGainian".equals(info.getSysKey())) {
                    iwencaiConfig.setFocusGaiNian(info.getSysValue());
                }

                if ("focusStocks".equals(info.getSysKey())) {
                    iwencaiConfig.setFocus(info.getSysValue());
                }

                if ("allOptional".equals(info.getSysKey())) {
                    iwencaiConfig.setAllOptional(info.getSysValue());
                }

                if ("gainianKeyword".equals(info.getSysKey())) {
                    iwencaiConfig.setGainianKeyword(info.getSysValue());
                }

                if ("searchKeyword".equals(info.getSysKey())) {
                    iwencaiConfig.setSearchKeyword(info.getSysValue());
                }

                if (info.getTypes() == 1) {
                    checksysInfos.add(info);
                    allcheck.setTypes(1);
                    allcheck.setSysKey("All策略");
                    allcheck.setSysValue(info.getSysValue()+","+allcheck.getSysValue());
                }
            }

            checksysInfos.add(allcheck);
            iwencaiConfig.setChecksysInfos(checksysInfos);
        }

//        WencaiKeywordService.findAllBy();

//        ThreadUtil.execAsync(() -> {
//            try {
//                cacheGainian = searchGainian(null);
//                // 启动立即跑一次热榜
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        });
//
//        ThreadUtil.execAsync(() -> {
//            List<StockHotRank> stockHotRanks = searchHot();
//            stockHotRankRepository.saveAll(stockHotRanks);
//        });

//        ThreadUtil.execAsync(() -> {
//            try {
//                log.info("执行获取涨停数据任务.....");
//                List<StockLimitUp> limitUpStocks = searchLimitUp("5月23日涨停");
//                if (!limitUpStocks.isEmpty()) {
//                    stockLimitUpRepository.saveAll(limitUpStocks);
//                    log.info("成功保存 {} 只涨停股票数据", limitUpStocks.size());
//                } else {
//                    log.info("未获取到涨停股票数据");
//                }
//            } catch (Exception e) {
//                log.error("执行涨停数据任务时发生异常", e);
//            }
//        });

    }

    public List<Map<String, Object>> searchGainian(String keyword) {
        if (StrUtil.isNotBlank(keyword)) {
            defKey = formatWithSimpleDateFormat(keyword);
        }
        String apiUrl = config.getUrl() + config.getSearchGainianUrl();
        log.info(apiUrl);
        HttpURLConnection conn = null;
        try {
            log.info("Gainian搜索关键词: {}", defKey);
            String encodedKey = URLEncoder.encode(defKey, "UTF-8");
            URL url = new URL(apiUrl + encodedKey);
            conn = (HttpURLConnection) url.openConnection();
            // 配置GET请求
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");

            // 获取响应状态码
            int statusCode = conn.getResponseCode();
            if (statusCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(conn.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;

                while ((line = in.readLine()) != null) {
                    response.append(line);
                }
                in.close();

                JSONObject jsonObj = JSONObject.parseObject(response.toString());
                log.info("概念总数: {}", jsonObj.getInteger("count"));

                // 获取data数组
                JSONArray dataArr = jsonObj.getJSONArray("data");
                List<Map<String, Object>> stocks = new ArrayList<>();
                for (int i = 0; i < dataArr.size(); i++) {
                    JSONObject stock = dataArr.getJSONObject(i);
                    Map<String, Object> stockMap = new HashMap<>();
                    stockMap.put("code", stock.getString("指数代码"));
                    stockMap.put("name", stock.getString("指数简称"));
                    stocks.add(stockMap);
                }
//                log.info("概念列表: {}", stocks);
                cacheGainian = stocks;
                return stocks;
            } else {
                log.error("请求概念失败，错误码: {}", statusCode);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return new ArrayList<>();
    }

    public List<StockHotRank> searchHot() {
        String keyword = config.getHotKeyword();
        String apiUrl = config.getUrl() + config.getHotUrl(); // 替换实际URL和参数
        log.info(apiUrl);
        try {
            if (keyword != null && !keyword.trim().isEmpty()) {
                keyword = formatWithSimpleDateFormat(keyword);
                log.info("热榜关键词: {}", keyword);
            }
            String encodedKey = URLEncoder.encode(keyword, "UTF-8");
            URL url = new URL(apiUrl + encodedKey);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            // 配置GET请求
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");

            // 获取响应状态码
            int statusCode = conn.getResponseCode();
            //  System.out.println("HTTP状态码: " + statusCode);

            // 处理响应
            if (statusCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(conn.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;

                while ((line = in.readLine()) != null) {
                    response.append(line);
                }
                in.close();

                // 解析为JSONObject
                JSONObject jsonObj = JSONObject.parseObject(response.toString());

                log.info("热度总数: {}", jsonObj.getInteger("count"));
                //   System.out.println("jsonObj: " + jsonObj);

                // 获取data数组
                JSONArray dataArr = jsonObj.getJSONArray("data");
                JSONObject firstItem = dataArr.getJSONObject(0);

                List<StockHotRank> stocks = new ArrayList<>();
                String yyyyMMdd = "[" + DateUtil.format(new Date(), "yyyyMMdd") + "]";
                String pd = ":前复权" + yyyyMMdd;
                LocalDateTime now = LocalDateTime.now();
                for (int i = 0; i < dataArr.size(); i++) {
                    /**
                     * code~:“002639~
                     * market code”:“33"个股热度[20250527]~:2194371,
                     * "个股热度排名[20250527]~:1,最新价" :"10.32~，最新涨跌幅" :"1.875616979~股票代码" :~002639.SZ~，股票简称" :""雪人股份
                     */
                    JSONObject stock = dataArr.getJSONObject(i);
                    //    System.out.println(stock.toJSONString());
                    StockHotRank stockHot = new StockHotRank();
                    stockHot.setStockCode(stock.getString("code"));
                    stockHot.setStockName(stock.getString("股票简称"));
                    stockHot.setCurrentPrice(stock.getBigDecimal("最新价"));
                    stockHot.setPriceChangePercent(stock.getBigDecimal("涨跌幅" + pd));
                    stockHot.setRankPosition(stock.getInteger("个股热度排名" + yyyyMMdd));
                    stockHot.setAttentionDegree(stock.getLong("个股热度" + yyyyMMdd));
                    stockHot.setRankDate(now);
                    stockHot.setCreateTime(now);
                    stockHot.setUpdateTime(now);
                    stocks.add(stockHot);
                }
                log.info("股票列表: {}", stocks);
                return stocks;

//                // 获取具体字段（自动处理Unicode转义）
//                System.out.println("股票简称: " + firstItem.getString("股票简称"));
//                System.out.println("股票代码: " + firstItem.getString("股票代码"));
//                System.out.println("响应内容: " + response.toString());
            } else {
                log.error("请求失败，错误码: {}", statusCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    public List<Map<String, Object>> searchStocks(String keyword, boolean isLocal) {
        String apiUrl = config.getUrl() + config.getSearchUrl(); // 替换实际URL和参数
        log.info(apiUrl);
        try {
            if (keyword != null && !keyword.trim().isEmpty()) {
                keyword = formatWithSimpleDateFormat(keyword);
                log.info("搜索关键词: {}", keyword);
            }
            JSONObject jsonObj = null;
            if (isLocal) {
                jsonObj = icService.searchStocksD(keyword);
            } else {
                String encodedKey = URLEncoder.encode(keyword, "UTF-8");
                URL url = new URL(apiUrl + encodedKey);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();

                // 配置GET请求
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept", "application/json");

                // 获取响应状态码
                int statusCode = conn.getResponseCode();
                //  System.out.println("HTTP状态码: " + statusCode);

                // 处理响应
                if (statusCode == HttpURLConnection.HTTP_OK) {
                    BufferedReader in = new BufferedReader(
                            new InputStreamReader(conn.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;

                    while ((line = in.readLine()) != null) {
                        response.append(line);
                    }
                    in.close();

                    // 解析为JSONObject
                    jsonObj = JSONObject.parseObject(response.toString());
                }
            }
            if (jsonObj == null) {
                log.error("本次查询无数据");
                return new ArrayList<>();
            }
            log.info("总数: {}", jsonObj.getInteger("count"));
//               System.out.println("jsonObj: " + jsonObj);

            // 获取data数组
            JSONArray dataArr = jsonObj.getJSONArray("data");
            JSONObject firstItem = dataArr.getJSONObject(0);
            System.out.println("jsonObj=:" + jsonObj);
            System.out.println("dataArr=:" + dataArr);
            List<Map<String, Object>> stocks = new ArrayList<>();
            String yyyyMMdd = "[" + DateUtil.format(new Date(), "yyyyMMdd") + "]";
            // 获取当前日期并减去一天
//            LocalDate yesterday = LocalDate.now().minusDays(1);
            LocalDate yesterday = DateUtils.minusDaysExcludeWeekendAndYesterday(LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT), 1).toLocalDate();
            // 格式化日期
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String yesterdayyyyyMMdd = "[" + yesterday.format(formatter) + "]";

            String pd = ":前复权" + yyyyMMdd;
            for (int i = 0; i < dataArr.size(); i++) {
                JSONObject stock = dataArr.getJSONObject(i);
                System.out.println(stock.toJSONString());
                Map<String, Object> stockMap = new HashMap<>();
                stockMap.put("code", stock.getString("股票代码").substring(0, 6));
                stockMap.put("name", stock.getString("股票简称"));
                Double zxj = stock.getDouble("最新价");
                if (zxj == null) {
                    zxj = stock.getDouble("收盘价:不复权" + yyyyMMdd);
                }
                stockMap.put("price", zxj);
                Double changePercent = stock.getDouble("涨跌幅" + pd);
                if (changePercent == null) {
                    changePercent = stock.getDouble("最新涨跌幅");
                }
                stockMap.put("changePercent", changePercent);
                stockMap.put("open", stock.getDouble("开盘价" + pd));
                stockMap.put("high", stock.getDouble("最高价" + pd));
                stockMap.put("low", stock.getDouble("最低价" + pd));
                stockMap.put("flow", stock.getLong("主力资金流向" + yyyyMMdd));

                String hangye = stock.getString("所属同花顺行业");
                stockMap.put("gainian", stock.getString("所属概念") + ";" + (hangye != null && !hangye.trim().isEmpty() ? hangye.replace("-", ";") : ""));

                String rankValue = stock.getString("个股热度排名" + yyyyMMdd); // 先获取字符串值
                stockMap.put("rank_position", getRank(rankValue));

                String oldRank = stock.getString("个股热度排名" + yesterdayyyyyMMdd);
                if (oldRank == null) {
                    oldRank = getOldRank(stock, 2);
                }
                stockMap.put("old_rank_position", getRank(oldRank));
                stockMap.put("mainCapitalFlow", stock.getBigDecimal("主力资金流向" + yyyyMMdd));
                stockMap.put("capitalFlow", stock.getBigDecimal("资金流向" + yyyyMMdd));

                stocks.add(stockMap);
                //  System.out.println(pd);
//                    String key = "开盘价" + pd;
//                    System.out.println(key);
//                    System.out.println(stock.getDouble(key));
            }
            log.info("股票列表: {}", stocks);
            return stocks;

//                // 获取具体字段（自动处理Unicode转义）
//                System.out.println("股票简称: " + firstItem.getString("股票简称"));
//                System.out.println("股票代码: " + firstItem.getString("股票代码"));
//                System.out.println("响应内容: " + response.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    public Long getRank(String rankValue) {
        if (rankValue == null || rankValue.trim().isEmpty()) {
            return 0L;
        }
        String[] parts = rankValue.split("/"); // 按"/"分割字符串
        if (parts.length > 0) {
            try {
                long rankPosition = Long.parseLong(parts[0]); // 转换第一部分为long
                return rankPosition;
            } catch (NumberFormatException e) {
                return 0l;
            }
        } else {
            return Long.parseLong(rankValue);
        }
    }

    /**
     * 获取涨停数据
     * @param keyword 搜索关键词，如果为空则使用默认关键词
     * @return 涨停股票列表
     */
    public List<StockLimitUp> searchLimitUp(String keyword, boolean isLocal) {
        String apiUrl = config.getUrl() + config.getSearchUrl(); // 使用现有的搜索URL配置
        log.info(apiUrl);
        try {
            if (keyword == null || keyword.trim().isEmpty()) {
                keyword = "涨停股票"; // 默认关键词
            }
            keyword = formatWithSimpleDateFormat(keyword);
            log.info("涨停搜索关键词: {}", keyword);
            JSONObject jsonObj = null;
            if (isLocal) {
                jsonObj = icService.searchStocksD(keyword);
            } else {
                String encodedKey = URLEncoder.encode(keyword, "UTF-8");
                URL url = new URL(apiUrl + encodedKey);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();

                // 配置GET请求
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept", "application/json");

                // 获取响应状态码
                int statusCode = conn.getResponseCode();

                // 处理响应
                if (statusCode == HttpURLConnection.HTTP_OK) {
                    BufferedReader in = new BufferedReader(
                            new InputStreamReader(conn.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;

                    while ((line = in.readLine()) != null) {
                        response.append(line);
                    }
                    in.close();
                    // 解析为JSONObject
                    jsonObj = JSONObject.parseObject(response.toString());
                }
            }
            if (jsonObj == null) {
                log.error("本次查询无数据");
                return new ArrayList<>();
            }
            log.info("涨停数据总数: {}", jsonObj.getInteger("count"));

            // 获取data数组
            JSONArray dataArr = jsonObj.getJSONArray("data");
            List<StockLimitUp> limitUpStocks = new ArrayList<>();
            String yyyyMMdd = "[" + DateUtil.format(new Date(), "yyyyMMdd") + "]";
            //    DateTime dateTime = DateUtil.offsetDay(new Date(), -7);
//                if (keyword.contains("5月23日涨停")) {
//                    yyyyMMdd = "[" + DateUtil.format(dateTime, "yyyyMMdd") + "]";
//                }
            LocalDateTime now = LocalDateTime.now();

            // 获取当前日期并减去一天
//            LocalDate yesterday = LocalDate.now().minusDays(1);
            LocalDate yesterday = DateUtils.minusDaysExcludeWeekendAndYesterday(LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT), 1).toLocalDate();
            // 格式化日期
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String yesterdayyyyyMMdd = "[" + yesterday.format(formatter) + "]";

//                if (keyword.contains("5月23日涨停")) {
//                    now = dateTime.toLocalDateTime();
//                }
            for (int i = 0; i < dataArr.size(); i++) {
                JSONObject stock = dataArr.getJSONObject(i);
                System.out.println("searchLimitUp==" + stock);
                StockLimitUp limitUp = new StockLimitUp();

                // 基础信息
                limitUp.setStockCode(stock.getString("code"));
                limitUp.setStockName(stock.getString("股票简称"));
                limitUp.setCurrentPrice(stock.getBigDecimal("最新价"));

                String hangye = stock.getString("所属同花顺行业");
                limitUp.setGainians(stock.getString("所属概念") + ";" + (hangye != null && !hangye.trim().isEmpty() ? hangye.replace("-", ";") : ""));
                limitUp.setPriceIncreasePercent(stock.getBigDecimal("最新涨跌幅"));

                // 涨停时间信息
                String firstLimitUpTimeStr = stock.getString("首次涨停时间" + yyyyMMdd);
                if (StrUtil.isNotBlank(firstLimitUpTimeStr)) {
                    try {
                        // 解析时间格式，假设格式为 " 14:27:54"
                        String timeStr = firstLimitUpTimeStr.trim();
                        LocalDateTime firstLimitUpTime = LocalDateTime.of(now.toLocalDate(),
                                java.time.LocalTime.parse(timeStr));
                        limitUp.setFirstLimitUpTime(firstLimitUpTime);
                    } catch (Exception e) {
                        log.warn("解析首次涨停时间失败: {}", firstLimitUpTimeStr);
                    }
                }

                String finalLimitUpTimeStr = stock.getString("最终涨停时间" + yyyyMMdd);
                if (StrUtil.isNotBlank(finalLimitUpTimeStr)) {
                    try {
                        String timeStr = finalLimitUpTimeStr.trim();
                        LocalDateTime finalLimitUpTime = LocalDateTime.of(now.toLocalDate(),
                                java.time.LocalTime.parse(timeStr));
                        limitUp.setFinalLimitUpTime(finalLimitUpTime);
                    } catch (Exception e) {
                        log.warn("解析最终涨停时间失败: {}", finalLimitUpTimeStr);
                    }
                }

                // 涨停详细信息
                limitUp.setLimitUpReason(stock.getString("涨停原因类别" + yyyyMMdd));
                limitUp.setLimitUpOrderVolume(stock.getLong("涨停封单量" + yyyyMMdd));
                limitUp.setSealOrderAmount(stock.getBigDecimal("涨停封单额" + yyyyMMdd));
                limitUp.setSealTurnoverRatio(stock.getBigDecimal("涨停封单量占成交量比" + yyyyMMdd));
                limitUp.setSealCirculationRatio(stock.getBigDecimal("涨停封单量占流通a股比" + yyyyMMdd));
                limitUp.setMainCapitalFlow(stock.getBigDecimal("主力资金流向" + yyyyMMdd));
                limitUp.setCapitalFlow(stock.getBigDecimal("资金流向" + yyyyMMdd));

                // 统计信息
                limitUp.setOpenBoardCount(stock.getInteger("涨停开板次数" + yyyyMMdd));
                limitUp.setConsecutiveLimitUpCount(stock.getString("几天几板" + yyyyMMdd));
                limitUp.setConsecutiveLimitUpDays(stock.getInteger("连续涨停天数" + yyyyMMdd));
                limitUp.setLimitUpType(stock.getString("涨停类型" + yyyyMMdd));

                limitUp.setRankPosition(stock.getLong("个股热度排名" + yyyyMMdd));
                String oldRank = stock.getString("个股热度排名" + yesterdayyyyyMMdd);
                if (oldRank == null) {
                    oldRank = getOldRank(stock, 2);
                }
                limitUp.setOldRankPosition(getRank(oldRank));

                // 时间戳
                limitUp.setRecordTime(now);
                limitUp.setCreateTime(now);
                limitUp.setUpdateTime(now);

                limitUpStocks.add(limitUp);
            }
            log.info("涨停股票列表: {}", limitUpStocks);
            return limitUpStocks;
        } catch (Exception e) {
            log.error("获取涨停数据时发生异常", e);
        }
        return new ArrayList<>();
    }

    /**
     * 获取跌停数据
     * @param keyword 搜索关键词，如果为空则使用默认关键词
     * @return 涨停股票列表
     */
    public List<StockLimitDown> searchLimitDown(String keyword, boolean isLocal) {
        String apiUrl = config.getUrl() + config.getSearchUrl(); // 使用现有的搜索URL配置
        log.info(apiUrl);
        try {
            if (keyword == null || keyword.trim().isEmpty()) {
                keyword = "跌停股票"; // 默认关键词
            }
            keyword = formatWithSimpleDateFormat(keyword);
            log.info("跌停搜索关键词: {}", keyword);
            JSONObject jsonObj = null;
            if (isLocal) {
                jsonObj = icService.searchStocksD(keyword);
            } else {
                String encodedKey = URLEncoder.encode(keyword, "UTF-8");
                URL url = new URL(apiUrl + encodedKey);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();

                // 配置GET请求
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept", "application/json");

                // 获取响应状态码
                int statusCode = conn.getResponseCode();

                // 处理响应
                if (statusCode == HttpURLConnection.HTTP_OK) {
                    BufferedReader in = new BufferedReader(
                            new InputStreamReader(conn.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;

                    while ((line = in.readLine()) != null) {
                        response.append(line);
                    }
                    in.close();
                    // 解析为JSONObject
                    jsonObj = JSONObject.parseObject(response.toString());
                }
            }
            if (jsonObj == null) {
                log.error("本次查询无数据");
                return new ArrayList<>();
            }
            log.info("跌停数据总数: {}", jsonObj.getInteger("count"));

            // 获取data数组
            JSONArray dataArr = jsonObj.getJSONArray("data");
            List<StockLimitDown> limitUpStocks = new ArrayList<>();
            String yyyyMMdd = "[" + DateUtil.format(new Date(), "yyyyMMdd") + "]";
            //    DateTime dateTime = DateUtil.offsetDay(new Date(), -7);
//                if (keyword.contains("5月23日跌停")) {
//                    yyyyMMdd = "[" + DateUtil.format(dateTime, "yyyyMMdd") + "]";
//                }
            LocalDateTime now = LocalDateTime.now();

            // 获取当前日期并减去一天
//            LocalDate yesterday = LocalDate.now().minusDays(1);
            LocalDate yesterday = DateUtils.minusDaysExcludeWeekendAndYesterday(LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT), 1).toLocalDate();
            // 格式化日期
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String yesterdayyyyyMMdd = "[" + yesterday.format(formatter) + "]";

//                if (keyword.contains("5月23日跌停")) {
//                    now = dateTime.toLocalDateTime();
//                }
            for (int i = 0; i < dataArr.size(); i++) {
                JSONObject stock = dataArr.getJSONObject(i);
                System.out.println("searchLimitUp==" + stock);
                StockLimitDown limitUp = new StockLimitDown();

                // 基础信息
                limitUp.setStockCode(stock.getString("code"));
                limitUp.setStockName(stock.getString("股票简称"));
                limitUp.setCurrentPrice(stock.getBigDecimal("最新价"));

                String hangye = stock.getString("所属同花顺行业");
                limitUp.setGainians(stock.getString("所属概念") + ";" + (hangye != null && !hangye.trim().isEmpty() ? hangye.replace("-", ";") : ""));
                limitUp.setPriceIncreasePercent(stock.getBigDecimal("最新涨跌幅"));

                // 涨停时间信息
                String firstLimitUpTimeStr = stock.getString("首次跌停时间" + yyyyMMdd);
                if (StrUtil.isNotBlank(firstLimitUpTimeStr)) {
                    try {
                        // 解析时间格式，假设格式为 " 14:27:54"
                        String timeStr = firstLimitUpTimeStr.trim();
                        LocalDateTime firstLimitUpTime = LocalDateTime.of(now.toLocalDate(),
                                java.time.LocalTime.parse(timeStr));
                        limitUp.setFirstLimitUpTime(firstLimitUpTime);
                    } catch (Exception e) {
                        log.warn("解析首次跌停时间失败: {}", firstLimitUpTimeStr);
                    }
                }

                String finalLimitUpTimeStr = stock.getString("最终跌停时间" + yyyyMMdd);
                if (StrUtil.isNotBlank(finalLimitUpTimeStr)) {
                    try {
                        String timeStr = finalLimitUpTimeStr.trim();
                        LocalDateTime finalLimitUpTime = LocalDateTime.of(now.toLocalDate(),
                                java.time.LocalTime.parse(timeStr));
                        limitUp.setFinalLimitUpTime(finalLimitUpTime);
                    } catch (Exception e) {
                        log.warn("解析最终跌停时间失败: {}", finalLimitUpTimeStr);
                    }
                }

                // 涨停详细信息
                limitUp.setLimitUpReason(stock.getString("跌停原因类别" + yyyyMMdd));
                limitUp.setLimitUpOrderVolume(stock.getLong("跌停封单量" + yyyyMMdd));
                limitUp.setSealOrderAmount(stock.getBigDecimal("跌停封单额" + yyyyMMdd));
                limitUp.setSealTurnoverRatio(stock.getBigDecimal("跌停封单量占成交量比" + yyyyMMdd));
                limitUp.setSealCirculationRatio(stock.getBigDecimal("跌停封单量占流通a股比" + yyyyMMdd));
                limitUp.setMainCapitalFlow(stock.getBigDecimal("主力资金流向" + yyyyMMdd));
                limitUp.setCapitalFlow(stock.getBigDecimal("资金流向" + yyyyMMdd));

                // 统计信息
                limitUp.setOpenBoardCount(stock.getInteger("跌停开板次数" + yyyyMMdd));
                limitUp.setConsecutiveLimitUpCount(stock.getString("几天几板" + yyyyMMdd));
                limitUp.setConsecutiveLimitUpDays(stock.getInteger("连续跌停天数" + yyyyMMdd));
                limitUp.setLimitUpType(stock.getString("跌停类型" + yyyyMMdd));

                limitUp.setRankPosition(stock.getLong("个股热度排名" + yyyyMMdd));
                String oldRank = stock.getString("个股热度排名" + yesterdayyyyyMMdd);
                if (oldRank == null) {
                    oldRank = getOldRank(stock, 2);
                }
                limitUp.setOldRankPosition(getRank(oldRank));

                // 时间戳
                limitUp.setRecordTime(now);
                limitUp.setCreateTime(now);
                limitUp.setUpdateTime(now);

                limitUpStocks.add(limitUp);
            }
            log.info("跌停股票列表: {}", limitUpStocks);
            return limitUpStocks;
        } catch (Exception e) {
            log.error("获取跌停数据时发生异常", e);
        }
        return new ArrayList<>();
    }

    /**
     * 获取当天所有的股票 TODO
     *
     * @param keyword
     * @param isLocal
     * @return
     */
//   {
//	"所属概念": "军工;专精特新;融资融券;西部大开发",
//	"六十分钟线分时boll(mid值)[20251029 14:00]": "13.752",
//	"code": "920519",
//	"资金流向[20251029]": "-216431.760",
//	"最新价": "14.2",
//	"boll(mid值)[20251029]": "13.697",
//	"个股热度排名[20251029]": "5326/5449",
//	"个股热度[20251028]": 9326.5,
//	"换手率[20251029]": "2.355",
//	"rsi(rsi12值)[20251029]": "56.666",
//	"rsi(rsi24值)[20251029]": "50.127",
//	"股票简称": "万德股份",
//	"boll(upper值)[20251029]": "14.378",
//	"obv(maobv)[20251029]": "10123.257",
//	"收盘价:不复权[20251028]": 13.71,
//	"最高价:不复权[20251029]": "14.21",
//	"boll(lower值)[20251029]": "13.014",
//	"rsi(rsi6值)[20251029]": "70.776",
//	"涨跌幅:前复权[20251029]": "3.574033552",
//	"market_code": "151",
//	"主力资金流向[20251029]": -536892.05,
//	"股票代码": "920519.BJ",
//	"个股热度[20251029]": 4340.5,
//	"个股热度排名[20251028]": "5441/5449",
//	"最低价:不复权[20251029]": "13.35",
//	"obv(obv值)[20251029]": "9976.186",
//	"六十分钟线分时boll(lower值)[20251029 14:00]": "13.591",
//	"所属同花顺行业": "基础化工-化学制品-其他化学制品",
//	"六十分钟线分时boll(upper值)[20251029 14:00]": "13.912",
//	"成交量[20251029]": "1483265",
//	"开盘价:不复权[20251029]": "13.7"
//}   个股涨幅，昨天收盘价格,热度排行榜,昨天热度排行排名,所属概念
    public List<Stock> searchAllStocks(String keyword, boolean isLocal) {
        String apiUrl = config.getUrl() + config.getSearchUrl(); // 替换实际URL和参数
        log.info(apiUrl);
        try {
            if (keyword != null && !keyword.trim().isEmpty()) {
                keyword = formatWithSimpleDateFormat(keyword);
                log.info("搜索关键词: {}", keyword);
            }
            JSONObject jsonObj = null;
            if (isLocal) {
                jsonObj = icService.searchStocksD(keyword);
            } else {
                String encodedKey = URLEncoder.encode(keyword, "UTF-8");
                URL url = new URL(apiUrl + encodedKey);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                // 配置GET请求
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept", "application/json");
                // 获取响应状态码
                int statusCode = conn.getResponseCode();
                // 处理响应
                if (statusCode == HttpURLConnection.HTTP_OK) {
                    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;

                    while ((line = in.readLine()) != null) {
                        response.append(line);
                    }
                    in.close();
                    // 解析为JSONObject
                    jsonObj = JSONObject.parseObject(response.toString());
                }
            }
            if (jsonObj == null) {
                log.error("本次查询无数据");
                return new ArrayList<>();
            }
            log.info("总数: {}", jsonObj.getInteger("count"));
//            System.out.println("searchAllStocks jsonObj: " + jsonObj);

//            String boll60key="六十分钟线分时boll";
            String boll60key="三十分钟线分时boll";
            // 获取data数组
            JSONArray dataArr = jsonObj.getJSONArray("data");
//            JSONObject firstItem = dataArr.getJSONObject(0);
//            System.out.println("jsonObj=:" + jsonObj);
//            System.out.println("dataArr=:"+dataArr);
            List<Stock> stocks = new ArrayList<>();
            List<Stock60Boll> stock60Bolls = new ArrayList<>();
            String yyyyMMdd = "[" + DateUtil.format(new Date(), "yyyyMMdd") + "]";
            // 获取当前日期并减去一天
//            LocalDate yesterday = LocalDate.now().minusDays(1);
            LocalDate yesterday = DateUtils.minusDaysExcludeWeekendAndYesterday(LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT), 1).toLocalDate();
            // 格式化日期
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String yesterdayyyyyMMdd = "[" + yesterday.format(formatter) + "]";

            String pd = ":前复权" + yyyyMMdd;
            String yespd = ":前复权" + yesterdayyyyyMMdd;
            String nopd = ":不复权" + yyyyMMdd;
            String yesnopd = ":不复权" + yesterdayyyyyMMdd;
            for (int i = 0; i < dataArr.size(); i++) {
                JSONObject stockJson = dataArr.getJSONObject(i);
//                System.out.println(stockJson.toJSONString());
                Stock stockMap = new Stock();
                stockMap.setCode(stockJson.getString("股票代码").substring(0, 6));
                stockMap.setName(stockJson.getString("股票简称"));
                Double zxj = stockJson.getDouble("最新价");
                stockMap.setClose(zxj == null ? 0.0 : zxj);
//                stockMap.put("price", zxj);
                stockMap.setChangePercent(stockJson.getDouble("涨跌幅" + pd));
                Double open = stockJson.getDouble("开盘价" + nopd);
                if (open == null) {
                    open = stockJson.getDouble("开盘价" + yesnopd);
                }
                if (open == null) {
                    open = 0.0;
                }
                stockMap.setOpen(open);

                Double high = stockJson.getDouble("最高价" + nopd);
                if (high == null) {
                    high = stockJson.getDouble("最高价" + yesnopd);
                }
                if (high == null) {
                    high = 0.0;
                }
                stockMap.setHigh(high);

                Double limitdo = stockJson.getDouble("跌停价" + yyyyMMdd);
                if (limitdo == null) {
                    limitdo = stockJson.getDouble("跌停价" + yesterdayyyyyMMdd);
                }
                if (limitdo == null) {
                    limitdo = 0.0;
                }
                stockMap.setLimitdown(limitdo);

                Double limitup = stockJson.getDouble("涨停价" + yyyyMMdd);
                if (limitup == null) {
                    limitup = stockJson.getDouble("涨停价" + yesterdayyyyyMMdd);
                }
                if (limitup == null) {
                    limitup = 0.0;
                }
                stockMap.setLimitup(limitup);

                Double low = stockJson.getDouble("最低价" + nopd);
                if (low == null) {
                    low = stockJson.getDouble("最低价" + yesnopd);
                }
                if (low == null) {
                    low = 0.0;
                }
                stockMap.setLow(low);

                Double turnoverRate = stockJson.getDouble("换手率" + yyyyMMdd);
                if (turnoverRate == null) {
                    turnoverRate = stockJson.getDouble("换手率" + yesterdayyyyyMMdd);
                }
                if (turnoverRate == null) {
                    turnoverRate = 0.0;
                }
                stockMap.setTurnoverRate(turnoverRate);

                Double vol = stockJson.getDouble("成交量" + yyyyMMdd);
                if (vol == null) {
                    vol = stockJson.getDouble("成交量" + yesterdayyyyyMMdd);
                }
                if (vol == null) {
                    vol = 0.0;
                }
                stockMap.setVolume(vol);

                Double rsi6 = stockJson.getDouble("rsi(rsi6值)" + yyyyMMdd);
                if (rsi6 == null) {
                    rsi6 = stockJson.getDouble("rsi(rsi6值)" + yesterdayyyyyMMdd);
                }
                if (rsi6 == null) {
                    rsi6 = 0.0;
                }
                stockMap.setRsi6(rsi6);

                Double rsi12 = stockJson.getDouble("rsi(rsi12值)" + yyyyMMdd);
                if (rsi12 == null) {
                    rsi12 = stockJson.getDouble("rsi(rsi12值)" + yesterdayyyyyMMdd);
                }
                if (rsi12 == null) {
                    rsi12 = 0.0;
                }
                stockMap.setRsi12(rsi12);

                Double rsi24 = stockJson.getDouble("rsi(rsi24值)" + yyyyMMdd);
                if (rsi24 == null) {
                    rsi24 = stockJson.getDouble("rsi(rsi24值)" + yesterdayyyyyMMdd);
                }
                if (rsi24 == null) {
                    rsi24 = 0.0;
                }
                stockMap.setRsi24(rsi24);

                Double maobv = stockJson.getDouble("obv(maobv)" + yyyyMMdd);
                if (maobv == null) {
                    maobv = stockJson.getDouble("obv(maobv)" + yesterdayyyyyMMdd);
                }
                if (maobv == null) {
                    maobv = 0.0;
                }
                stockMap.setMaobv(maobv);

                Double obv = stockJson.getDouble("obv(obv值)" + yyyyMMdd);
                if (obv == null) {
                    obv = stockJson.getDouble("obv(obv值)" + yesterdayyyyyMMdd);
                }
                if (obv == null) {
                    obv = 0.0;
                }
                stockMap.setObv(obv);

                Double bollLower = stockJson.getDouble("boll(lower值)" + yyyyMMdd);
                if (bollLower == null) {
                    bollLower = stockJson.getDouble("boll(lower值)" + yesterdayyyyyMMdd);
                }
                if (bollLower == null) {
                    bollLower = 0.0;
                }
                stockMap.setBollLower(bollLower);

                Double bollMid = stockJson.getDouble("boll(mid值)" + yyyyMMdd);
                if (bollMid == null) {
                    bollMid = stockJson.getDouble("boll(mid值)" + yesterdayyyyyMMdd);
                }
                if (bollMid == null) {
                    bollMid = 0.0;
                }
                stockMap.setBollMid(bollMid);

                Double bollUpper = stockJson.getDouble("boll(upper值)" + yyyyMMdd);
                if (bollUpper == null) {
                    bollUpper = stockJson.getDouble("boll(upper值)" + yesterdayyyyyMMdd);
                }
                if (bollUpper == null) {
                    bollUpper = 0.0;
                }
                stockMap.setBollUpper(bollUpper);

                stockMap.setTradeDate(LocalDate.now());
                stockMap.setDate(DateUtil.format(new Date(), "yyyy-MM-dd"));
                stockMap.setMainCapitalFlow(stockJson.getBigDecimal("主力资金流向" + yyyyMMdd));
                stockMap.setCapitalFlow(stockJson.getBigDecimal("资金流向" + yyyyMMdd));
                stockMap.setMarketValue(stockJson.getDoubleValue("a股市值(不含限售股)" + yyyyMMdd));

                String rankValue = stockJson.getString("个股热度排名" + yyyyMMdd); // 先获取字符串值
                stockMap.setRankPosition(getRank(rankValue));

                String oldRank = stockJson.getString("个股热度排名" + yesterdayyyyyMMdd);
                if (oldRank == null) {
                    oldRank = getOldRank(stockJson, 2);
                }
                stockMap.setOldRankPosition(getRank(oldRank));


//              stockMap.put("flow", stockJson.getLong("主力资金流向" + yyyyMMdd));
                String hangye = stockJson.getString("所属同花顺行业");
                String[] hangyes = hangye.split("-");
                String sunhang = "";
                if (hangyes != null && hangyes.length >= 2) {
                    sunhang = hangyes[1] + ";";
                }
                stockMap.setConcept(sunhang + stockJson.getString("所属概念") + ";" + (hangye != null && !hangye.trim().isEmpty() ? hangye.replace("-", ";") : ""));
//                stockMap.put("rank_position", stockJson.getLong("个股热度排名" + yyyyMMdd));
//                Long oldRank=stockJson.getLong("个股热度排名" + yesterdayyyyyMMdd);
//                if (oldRank==null){
//                    oldRank=getOldRank(stock,2);
//                }
//                stockMap.put("old_rank_position", oldRank);
                stocks.add(stockMap);
                Stock60Boll stock60Boll = getKeyValuesByPrefix(stockMap,stockJson, boll60key,stockMap.getClose());
                if (stock60Boll!=null){
                    LocalDateTime createdAt = LocalDateTime.now();
                    stock60Boll.setCreatedTime(createdAt);
                    stock60Bolls.add(stock60Boll);
                }
                //  System.out.println(pd);
//                    String key = "开盘价" + pd;
//                    System.out.println(key);
//                    System.out.println(stockJson.getDouble(key));
            }
//            log.info("股票列表: {}", stocks);
//            System.out.println("stock60Bolls=="+stock60Bolls);
            stock60BollService.saveOrUpdateAll(stock60Bolls);
            return stocks;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("searchAllStocks: {}", e.getMessage());
        }
        return new ArrayList<>();
    }

    /**
     * 模糊获取以指定前缀开头的所有key-value对
     * @param jsonObject 源JSONObject
     * @param prefix 前缀
     * @return 包含匹配key-value的新JSONObject
     */
    public static Stock60Boll getKeyValuesByPrefix(Stock stockMap,JSONObject jsonObject, String prefix,double close) {
        if (jsonObject == null || prefix == null || prefix.isEmpty()) {
            return null;
        }

        if (stockMap == null ) {
            return null;
        }
//        "六十分钟线分时boll(mid值)[20251029 11:30]": "38.491",
//                "六十分钟线分时boll(lower值)[20251029 11:30]": "37.954",
//                "六十分钟线分时boll(upper值)[20251029 11:30]": "39.028",

        Stock60Boll stock60Boll = new Stock60Boll();
        stock60Boll.setCode(stockMap.getCode());
        stock60Boll.setName(stockMap.getName());
        stock60Boll.setTradeDate(LocalDate.now());

//        String midKey="(mid值)";
//        String lowerkey="(lower值)";
//        String upperkey="(upper值)";

        // 定义Bollinger Bands的类型
        String midKey = "(mid值)";
        String lowerKey = "(lower值)";
        String upperKey = "(upper值)";

        // 定义时间点
        String currentDate = DateUtil.format(new Date(), "yyyyMMdd");
        String[] timePoints = {
                currentDate + " 9:30",
                currentDate + " 10:00",
                currentDate + " 10:30",
                currentDate + " 11:00",
                currentDate + " 11:30",
                currentDate + " 13:00",
                currentDate + " 13:30",
                currentDate + " 14:00",
                currentDate + " 14:30",
                currentDate + " 15:00"
        };
        // 处理9:30的数据
        String boll9Key = "[" + timePoints[0] + "]";
        Double boll9Mid = jsonObject.getDouble(prefix + midKey + boll9Key);
        Double boll9Low = jsonObject.getDouble(prefix + lowerKey + boll9Key);
        Double boll9Up = jsonObject.getDouble(prefix + upperKey + boll9Key);
        stock60Boll.setBoll9(formatBollValue(boll9Mid, boll9Low, boll9Up,close));

        // 处理10:00和10:30的数据 - 取非null的值
        String boll10Key1 = "[" + timePoints[1] + "]"; // 10:00
        String boll10Key2 = "[" + timePoints[2] + "]"; // 10:30

        Double boll10Mid = getNonNullValue(
                jsonObject.getDouble(prefix + midKey + boll10Key1),
                jsonObject.getDouble(prefix + midKey + boll10Key2)
        );
        Double boll10Low = getNonNullValue(
                jsonObject.getDouble(prefix + lowerKey + boll10Key1),
                jsonObject.getDouble(prefix + lowerKey + boll10Key2)
        );
        Double boll10Up = getNonNullValue(
                jsonObject.getDouble(prefix + upperKey + boll10Key1),
                jsonObject.getDouble(prefix + upperKey + boll10Key2)
        );
        stock60Boll.setBoll10(formatBollValue(boll10Mid, boll10Low, boll10Up, close));

//        // 处理10:30的数据
//        String boll10Key = "[" + timePoints[1] + "]";
//        Double boll10Mid = jsonObject.getDouble(prefix + midKey + boll10Key);
//        Double boll10Low = jsonObject.getDouble(prefix + lowerKey + boll10Key);
//        Double boll10Up = jsonObject.getDouble(prefix + upperKey + boll10Key);
//        stock60Boll.setBoll10(formatBollValue(boll10Mid, boll10Low, boll10Up,close));

        // 处理11:30的数据
//        String boll11Key = "[" + timePoints[2] + "]";
//        Double boll11Mid = jsonObject.getDouble(prefix + midKey + boll11Key);
//        Double boll11Low = jsonObject.getDouble(prefix + lowerKey + boll11Key);
//        Double boll11Up = jsonObject.getDouble(prefix + upperKey + boll11Key);
//        stock60Boll.setBoll11(formatBollValue(boll11Mid, boll11Low, boll11Up,close));
//
//        // 处理13:00的数据
//        String boll13Key = "[" + timePoints[3] + "]";
//        Double boll13Mid = jsonObject.getDouble(prefix + midKey + boll13Key);
//        Double boll13Low = jsonObject.getDouble(prefix + lowerKey + boll13Key);
//        Double boll13Up = jsonObject.getDouble(prefix + upperKey + boll13Key);
//        stock60Boll.setBoll13(formatBollValue(boll13Mid, boll13Low, boll13Up,close));
//
//        // 处理14:00的数据
//        String boll14Key = "[" + timePoints[4] + "]";
//        Double boll14Mid = jsonObject.getDouble(prefix + midKey + boll14Key);
//        Double boll14Low = jsonObject.getDouble(prefix + lowerKey + boll14Key);
//        Double boll14Up = jsonObject.getDouble(prefix + upperKey + boll14Key);
//        stock60Boll.setBoll14(formatBollValue(boll14Mid, boll14Low, boll14Up,close));

        // 处理11:00和11:30的数据 - 取非null的值
        String boll11Key1 = "[" + timePoints[3] + "]"; // 11:00
        String boll11Key2 = "[" + timePoints[4] + "]"; // 11:30

        Double boll11Mid = getNonNullValue(
                jsonObject.getDouble(prefix + midKey + boll11Key1),
                jsonObject.getDouble(prefix + midKey + boll11Key2)
        );
        Double boll11Low = getNonNullValue(
                jsonObject.getDouble(prefix + lowerKey + boll11Key1),
                jsonObject.getDouble(prefix + lowerKey + boll11Key2)
        );
        Double boll11Up = getNonNullValue(
                jsonObject.getDouble(prefix + upperKey + boll11Key1),
                jsonObject.getDouble(prefix + upperKey + boll11Key2)
        );
        stock60Boll.setBoll11(formatBollValue(boll11Mid, boll11Low, boll11Up, close));

        // 处理13:00和13:30的数据 - 取非null的值
        String boll13Key1 = "[" + timePoints[5] + "]"; // 13:00
        String boll13Key2 = "[" + timePoints[6] + "]"; // 13:30

        Double boll13Mid = getNonNullValue(
                jsonObject.getDouble(prefix + midKey + boll13Key1),
                jsonObject.getDouble(prefix + midKey + boll13Key2)
        );
        Double boll13Low = getNonNullValue(
                jsonObject.getDouble(prefix + lowerKey + boll13Key1),
                jsonObject.getDouble(prefix + lowerKey + boll13Key2)
        );
        Double boll13Up = getNonNullValue(
                jsonObject.getDouble(prefix + upperKey + boll13Key1),
                jsonObject.getDouble(prefix + upperKey + boll13Key2)
        );
        stock60Boll.setBoll13(formatBollValue(boll13Mid, boll13Low, boll13Up, close));

        // 处理14:00和14:30的数据 - 取非null的值
        String boll14Key1 = "[" + timePoints[7] + "]"; // 14:00
        String boll14Key2 = "[" + timePoints[8] + "]"; // 14:30

        Double boll14Mid = getNonNullValue(
                jsonObject.getDouble(prefix + midKey + boll14Key1),
                jsonObject.getDouble(prefix + midKey + boll14Key2)
        );
        Double boll14Low = getNonNullValue(
                jsonObject.getDouble(prefix + lowerKey + boll14Key1),
                jsonObject.getDouble(prefix + lowerKey + boll14Key2)
        );
        Double boll14Up = getNonNullValue(
                jsonObject.getDouble(prefix + upperKey + boll14Key1),
                jsonObject.getDouble(prefix + upperKey + boll14Key2)
        );
        stock60Boll.setBoll14(formatBollValue(boll14Mid, boll14Low, boll14Up, close));

        // 处理15:00的数据
        String boll15Key = "[" + timePoints[9] + "]";
        Double boll15Mid = jsonObject.getDouble(prefix + midKey + boll15Key);
        Double boll15Low = jsonObject.getDouble(prefix + lowerKey + boll15Key);
        Double boll15Up = jsonObject.getDouble(prefix + upperKey + boll15Key);
        stock60Boll.setBoll15(formatBollValue(boll15Mid, boll15Low, boll15Up,close));
        // 方法1：使用keySet遍历
//        for (String key : jsonObject.keySet()) {
//            if (key != null && key.startsWith(prefix)) {
//                result.put(key, jsonObject.get(key));
//            }
//        }
        return stock60Boll;
    }

    /**
     * 获取两个值中第一个非null的值
     */
    private static Double getNonNullValue(Double value1, Double value2) {
        return (value1 != null) ? value1 : value2;
    }

    /**
     * 格式化Bollinger Bands值为字符串
     * @param mid 中间值
     * @param low 下限值
     * @param up 上限值
     * @return 格式化后的字符串，格式为"mid#low#up"
     */
    private static String formatBollValue(Double mid, Double low, Double up, Double close) {
        // 如果所有值都为null，返回空字符串
        if (close == null || close == 0) {
            return "";
        }

        if (mid == null && low == null && up == null) {
            return "";
        }

        // 使用StringBuilder构建结果字符串
        StringBuilder sb = new StringBuilder();
        sb.append(mid != null ? mid : "");
        sb.append("#");
        sb.append(low != null ? low : "");
        sb.append("#");
        sb.append(up != null ? up : "");
        sb.append("#");
        sb.append(close != null ? close : "");

        return sb.toString();
    }

    /**
     * 使用泛型方法获取JSON中的值，提供默认值
     * @param jsonObject JSON对象
     * @param key 键名
     * @param defaultValue 默认值
     * @return 获取到的值或默认值
     */
    private static <T> T getValueWithDefault(JSONObject jsonObject, String key, T defaultValue) {
        try {
            if (jsonObject.containsKey(key)) {
                Object value = jsonObject.get(key);
                return value != null ? (T) value : defaultValue;
            }
        } catch (Exception e) {
            // 忽略异常，返回默认值
        }
        return defaultValue;
    }

    /**
     * {
     * "主力持仓成本[20250822]": 1433.5590220918166,
     * "code": "600519",
     * "最新价": "1463.95",
     * "股票简称": "贵州茅台",
     * "最新涨跌幅": "1.084066977",
     * "market_code": "17",
     * "股票代码": "600519.SH"
     * }
     * 获取主力成本
     *
     * @param keyword
     * @param isLocal
     * @return
     */
    public Map<String, Double> searchStocksMaincost(String keyword, boolean isLocal, LocalDate endDatesearch) {
        String apiUrl = config.getUrl() + config.getSearchUrl(); // 替换实际URL和参数
        log.info(apiUrl);
        try {
            if (keyword != null && !keyword.trim().isEmpty()) {
                keyword = formatWithSimpleDateFormat(keyword);
                log.info("搜索关键词: {}", keyword);
            }
            JSONObject jsonObj = null;
            if (isLocal) {
                jsonObj = icService.searchStocksD(keyword);
            } else {
                String encodedKey = URLEncoder.encode(keyword, "UTF-8");
                URL url = new URL(apiUrl + encodedKey);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                // 配置GET请求
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept", "application/json");
                // 获取响应状态码
                int statusCode = conn.getResponseCode();
                // 处理响应
                if (statusCode == HttpURLConnection.HTTP_OK) {
                    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;

                    while ((line = in.readLine()) != null) {
                        response.append(line);
                    }
                    in.close();
                    // 解析为JSONObject
                    jsonObj = JSONObject.parseObject(response.toString());
                }
            }
            if (jsonObj == null) {
                log.error("本次查询无数据");
                return new HashMap<>();
            }
            log.info("searchStocksMaincost 总数: {}", jsonObj.getInteger("count") + "searchStocksMaincost== jsonObj: " + jsonObj);

            // 获取data数组
            JSONArray dataArr = jsonObj.getJSONArray("data");
            Map<String, Double> stocks = new HashMap<>();
//            String yyyyMMdd = "[" + DateUtil.format(endDatesearch, "yyyyMMdd") + "]";
            // 获取当前日期并减去一天
//            LocalDate yesterday = LocalDate.now().minusDays(1);
            // 格式化日期
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            String yesterdayyyyyMMdd = "[" + endDatesearch.format(formatter) + "]";

            String pd = "主力持仓成本" + yesterdayyyyyMMdd;

            //String yespd = "主力持仓成本" + yesterdayyyyyMMdd;

            for (int i = 0; i < dataArr.size(); i++) {
                JSONObject stockJson = dataArr.getJSONObject(i);
                stocks.put(stockJson.getString("code").substring(0, 6), parseNumbers(stockJson.getString(pd)));
            }
//            log.info("股票主力列表: {}", stocks);
            return stocks;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("searchAllStocks: {}", e.getMessage());
        }
        return new HashMap<>();
    }

    /**
     * 获取所有指数 TODO
     *
     * @param keyword
     * @return
     */
//    {
//    "code": "883974",
//    "指数@收盘价:不复权[20251110]": "1264.320",
//    "指数@同花顺板块指数": "同花顺特色指数",
//    "指数@资金流向[20251110]": -190871890,
//    "指数@boll(mid值)[20251110]": "1262.619",
//    "指数简称": "远端次新股",
//    "三十分钟线指数@分时boll(mid值)[20251110 11:30]": "1270.857",
//    "market_code": "48",
//    "指数@板块热度排名名次[20251109]": 710,
//    "指数代码": "883974.TI",
//    "三十分钟线指数@分时boll(upper值)[20251110 11:30]": "1279.944",
//    "指数@boll(upper值)[20251110]": "1295.942",
//    "指数@板块热度排名[20251109]": "710/1328",
//    "指数@板块热度排名基数[20251110]": 1328,
//    "指数@板块热度排名[20251110]": "710/1328",
//    "指数@boll(lower值)[20251110]": "1229.296",
//    "三十分钟线指数@分时boll(lower值)[20251110 11:30]": "1261.786",
//    "指数@板块热度排名名次[20251110]": 710,
//    "指数@板块热度排名基数[20251109]": 1328,
//    "指数@涨跌幅:前复权[20251110]": "-0.0622",
//    "指数@总市值[20251110]": "938364330000.000"
//}   所有指数板块，资金
    public List<GaiNianInfo> searchAllGainian(String keyword) {
        if (StrUtil.isNotBlank(keyword)) {
            defKey = formatWithSimpleDateFormat(keyword);
        }
        String apiUrl = config.getUrl() + config.getSearchGainianUrl();
        log.info(apiUrl);
        HttpURLConnection conn = null;
        String boll60key="三十分钟线指数@分时boll";

        List<Gainian60Boll> gainian60Bolls = new ArrayList<>();
        try {
            log.info("Gainian搜索关键词: {}", defKey);
            String encodedKey = URLEncoder.encode(defKey, "UTF-8");
            URL url = new URL(apiUrl + encodedKey);
            conn = (HttpURLConnection) url.openConnection();
            // 配置GET请求
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");

            // 获取响应状态码
            int statusCode = conn.getResponseCode();
            if (statusCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(conn.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;

                while ((line = in.readLine()) != null) {
                    response.append(line);
                }
                in.close();

                JSONObject jsonObj = JSONObject.parseObject(response.toString());
                String yyyyMMdd = "[" + DateUtil.format(new Date(), "yyyyMMdd") + "]";
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");

//                LocalDate yesterday = LocalDate.now().minusDays(1);
                LocalDate yesterday = LocalDate.now().minusDays(1);//DateUtils.minusDaysExcludeWeekendAndYesterday(LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT), 1).toLocalDate();
                LocalDate yesterWorkday = DateUtils.minusDaysExcludeWeekendAndYesterday(LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT), 1).toLocalDate();
                ;
                String yesterdayyyyyMMdd = "[" + yesterday.format(formatter) + "]";
                String yesterWorkdayMMdd = "[" + yesterWorkday.format(formatter) + "]";

//                String pd = ":前复权" + yyyyMMdd;

                log.info("概念总数: {}", jsonObj.getInteger("count"));

                // 获取data数组
                JSONArray dataArr = jsonObj.getJSONArray("data");
                List<GaiNianInfo> stocks = new ArrayList<>();
                for (int i = 0; i < dataArr.size(); i++) {
                    JSONObject stock = dataArr.getJSONObject(i);
//                    System.out.println("searchAllGainian jsonObj: " + stock);
//                    Map<String, Object> stockMap = new HashMap<>();
                    GaiNianInfo gaiNianInfo = new GaiNianInfo();
                    String code = stock.getString("指数代码").substring(0, 6);
                    if (code == null || code.compareTo("800000") < 0) {
                        continue;
                    }
                    gaiNianInfo.setGainianCode(code);
                    gaiNianInfo.setGainianName(stock.getString("指数简称"));
                    gaiNianInfo.setIncreasePercent(stock.getBigDecimal("指数@涨跌幅:前复权" + yyyyMMdd));//"指数@涨跌幅:前复权"+yyyyMMdd
                    gaiNianInfo.setSealOrderAmount(stock.getBigDecimal("指数@资金流向" + yyyyMMdd));
                    gaiNianInfo.setCurrentPrice(stock.getBigDecimal("指数@收盘价:不复权" + yyyyMMdd));
                    String urrentPrice = stock.getString("指数@总市值" + yyyyMMdd);
                    Double urrentPrices = stock.getDouble("指数@涨跌幅:前复权" + yyyyMMdd);
//                    System.out.println(urrentPrice);
                    gaiNianInfo.setMarketValue(convertToNumber(urrentPrice));
                    gaiNianInfo.setChangePercent(urrentPrices);


                    String rankValue = stock.getString("指数@板块热度排名名次" + yyyyMMdd); // 先获取字符串值
                    gaiNianInfo.setRankPosition(getRank(rankValue));

                    String oldRank = stock.getString("指数@板块热度排名名次" + yesterdayyyyyMMdd);
                    if (oldRank == null) {
                        oldRank = getOldGaiRank(stock, 2);
                    }
                    gaiNianInfo.setOldRankPosition(getRank(oldRank));

                    Double bollLower = stock.getDouble("指数@boll(lower值)" + yyyyMMdd);
                    if (bollLower == null) {
                        bollLower = stock.getDouble("指数@boll(lower值)" + yesterWorkdayMMdd);
                    }
                    if (bollLower == null) {
                        bollLower = 0.0;
                    }
                    gaiNianInfo.setBollLower(bollLower);

                    Double bollMid = stock.getDouble("指数@boll(mid值)" + yyyyMMdd);
                    if (bollMid == null) {
                        bollMid = stock.getDouble("指数@boll(mid值)" + yesterWorkdayMMdd);
                    }
                    if (bollMid == null) {
                        bollMid = 0.0;
                    }
                    gaiNianInfo.setBollMid(bollMid);

                    Double bollUpper = stock.getDouble("指数@boll(upper值)" + yyyyMMdd);
                    if (bollUpper == null) {
                        bollUpper = stock.getDouble("指数@boll(upper值)" + yesterWorkdayMMdd);
                    }
                    if (bollUpper == null) {
                        bollUpper = 0.0;
                    }
                    gaiNianInfo.setBollUpper(bollUpper);
                    stocks.add(gaiNianInfo);

                    Gainian60Boll stock60Boll = getGainianKeyValuesByPrefix(gaiNianInfo,stock, boll60key,gaiNianInfo.getCurrentPrice()==null?0.0:gaiNianInfo.getCurrentPrice().doubleValue());
                    if (stock60Boll!=null){
                        LocalDateTime createdAt = LocalDateTime.now();
                        stock60Boll.setCreatedTime(createdAt);
                        gainian60Bolls.add(stock60Boll);
                    }
                }

//                System.out.println("gainian60Bolls=="+gainian60Bolls);
                // 三元运算符判断：不为null输出size()，为null输出"null"（可自定义）
                System.out.println("gainian60Bolls==" + (gainian60Bolls != null ? gainian60Bolls.size() : "null"));
                gainian60BollService.saveOrUpdateAll(gainian60Bolls);
//                log.info("概念列表: {}", stocks);
                return stocks;
            } else {
                log.error("请求概念失败，错误码: {}", statusCode);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }


    /**
     * 模糊获取以指定前缀开头的所有key-value对
     * @param jsonObject 源JSONObject
     * @param prefix 前缀
     * @return 包含匹配key-value的新JSONObject
     */
    public static Gainian60Boll getGainianKeyValuesByPrefix(GaiNianInfo stockMap, JSONObject jsonObject, String prefix, double close) {
        if (jsonObject == null || prefix == null || prefix.isEmpty()) {
            return null;
        }

        if (stockMap == null ) {
            return null;
        }
//        "六十分钟线分时boll(mid值)[20251029 11:30]": "38.491",
//                "六十分钟线分时boll(lower值)[20251029 11:30]": "37.954",
//                "六十分钟线分时boll(upper值)[20251029 11:30]": "39.028",

        Gainian60Boll stock60Boll = new Gainian60Boll();
        stock60Boll.setCode(stockMap.getGainianCode());
        stock60Boll.setName(stockMap.getGainianName());
        stock60Boll.setTradeDate(LocalDate.now());

//        String midKey="(mid值)";
//        String lowerkey="(lower值)";
//        String upperkey="(upper值)";

        // 定义Bollinger Bands的类型
        String midKey = "(mid值)";
        String lowerKey = "(lower值)";
        String upperKey = "(upper值)";

        // 定义时间点
        String currentDate = DateUtil.format(new Date(), "yyyyMMdd");
        String[] timePoints = {
                currentDate + " 9:30",
                currentDate + " 10:00",
                currentDate + " 10:30",
                currentDate + " 11:00",
                currentDate + " 11:30",
                currentDate + " 13:00",
                currentDate + " 13:30",
                currentDate + " 14:00",
                currentDate + " 14:30",
                currentDate + " 15:00"
        };
        // 处理9:30的数据
        String boll9Key = "[" + timePoints[0] + "]";
        Double boll9Mid = jsonObject.getDouble(prefix + midKey + boll9Key);
        Double boll9Low = jsonObject.getDouble(prefix + lowerKey + boll9Key);
        Double boll9Up = jsonObject.getDouble(prefix + upperKey + boll9Key);
        stock60Boll.setBoll9(formatBollValue(boll9Mid, boll9Low, boll9Up,close));

        // 处理10:00和10:30的数据 - 取非null的值
        String boll10Key1 = "[" + timePoints[1] + "]"; // 10:00
        String boll10Key2 = "[" + timePoints[2] + "]"; // 10:30

        Double boll10Mid = getNonNullValue(
                jsonObject.getDouble(prefix + midKey + boll10Key1),
                jsonObject.getDouble(prefix + midKey + boll10Key2)
        );
        Double boll10Low = getNonNullValue(
                jsonObject.getDouble(prefix + lowerKey + boll10Key1),
                jsonObject.getDouble(prefix + lowerKey + boll10Key2)
        );
        Double boll10Up = getNonNullValue(
                jsonObject.getDouble(prefix + upperKey + boll10Key1),
                jsonObject.getDouble(prefix + upperKey + boll10Key2)
        );
        stock60Boll.setBoll10(formatBollValue(boll10Mid, boll10Low, boll10Up, close));

        // 处理11:00和11:30的数据 - 取非null的值
        String boll11Key1 = "[" + timePoints[3] + "]"; // 11:00
        String boll11Key2 = "[" + timePoints[4] + "]"; // 11:30

        Double boll11Mid = getNonNullValue(
                jsonObject.getDouble(prefix + midKey + boll11Key1),
                jsonObject.getDouble(prefix + midKey + boll11Key2)
        );
        Double boll11Low = getNonNullValue(
                jsonObject.getDouble(prefix + lowerKey + boll11Key1),
                jsonObject.getDouble(prefix + lowerKey + boll11Key2)
        );
        Double boll11Up = getNonNullValue(
                jsonObject.getDouble(prefix + upperKey + boll11Key1),
                jsonObject.getDouble(prefix + upperKey + boll11Key2)
        );
        stock60Boll.setBoll11(formatBollValue(boll11Mid, boll11Low, boll11Up, close));

        // 处理13:00和13:30的数据 - 取非null的值
        String boll13Key1 = "[" + timePoints[5] + "]"; // 13:00
        String boll13Key2 = "[" + timePoints[6] + "]"; // 13:30

        Double boll13Mid = getNonNullValue(
                jsonObject.getDouble(prefix + midKey + boll13Key1),
                jsonObject.getDouble(prefix + midKey + boll13Key2)
        );
        Double boll13Low = getNonNullValue(
                jsonObject.getDouble(prefix + lowerKey + boll13Key1),
                jsonObject.getDouble(prefix + lowerKey + boll13Key2)
        );
        Double boll13Up = getNonNullValue(
                jsonObject.getDouble(prefix + upperKey + boll13Key1),
                jsonObject.getDouble(prefix + upperKey + boll13Key2)
        );
        stock60Boll.setBoll13(formatBollValue(boll13Mid, boll13Low, boll13Up, close));

        // 处理14:00和14:30的数据 - 取非null的值
        String boll14Key1 = "[" + timePoints[7] + "]"; // 14:00
        String boll14Key2 = "[" + timePoints[8] + "]"; // 14:30

        Double boll14Mid = getNonNullValue(
                jsonObject.getDouble(prefix + midKey + boll14Key1),
                jsonObject.getDouble(prefix + midKey + boll14Key2)
        );
        Double boll14Low = getNonNullValue(
                jsonObject.getDouble(prefix + lowerKey + boll14Key1),
                jsonObject.getDouble(prefix + lowerKey + boll14Key2)
        );
        Double boll14Up = getNonNullValue(
                jsonObject.getDouble(prefix + upperKey + boll14Key1),
                jsonObject.getDouble(prefix + upperKey + boll14Key2)
        );
        stock60Boll.setBoll14(formatBollValue(boll14Mid, boll14Low, boll14Up, close));

        // 处理15:00的数据
        String boll15Key = "[" + timePoints[9] + "]";
        Double boll15Mid = jsonObject.getDouble(prefix + midKey + boll15Key);
        Double boll15Low = jsonObject.getDouble(prefix + lowerKey + boll15Key);
        Double boll15Up = jsonObject.getDouble(prefix + upperKey + boll15Key);
        stock60Boll.setBoll15(formatBollValue(boll15Mid, boll15Low, boll15Up,close));
        // 方法1：使用keySet遍历
//        for (String key : jsonObject.keySet()) {
//            if (key != null && key.startsWith(prefix)) {
//                result.put(key, jsonObject.get(key));
//            }
//        }
        return stock60Boll;
    }

    /**
     * 15分钟KDJ
     * @param keyword
     * @param isLocal
     * @return
     */
    public Map<String, Stock> searchKDJStocks(String keyword, boolean isLocal) {
        String apiUrl = config.getUrl() + config.getSearchUrl(); // 替换实际URL和参数
        log.info(apiUrl);
        try {
            if (keyword != null && !keyword.trim().isEmpty()) {
                keyword = formatWithSimpleDateFormat(keyword);
                log.info("搜索关键词: {}", keyword);
            }
            JSONObject jsonObj = null;
            if (isLocal) {
                jsonObj = icService.searchStocksD(keyword);
            } else {
                String encodedKey = URLEncoder.encode(keyword, "UTF-8");
                URL url = new URL(apiUrl + encodedKey);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                // 配置GET请求
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Accept", "application/json");
                // 获取响应状态码
                int statusCode = conn.getResponseCode();
                // 处理响应
                if (statusCode == HttpURLConnection.HTTP_OK) {
                    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    StringBuilder response = new StringBuilder();
                    String line;

                    while ((line = in.readLine()) != null) {
                        response.append(line);
                    }
                    in.close();
                    // 解析为JSONObject
                    jsonObj = JSONObject.parseObject(response.toString());
                }
            }
            if (jsonObj == null) {
                log.error("本次查询无数据");
                return new HashMap<>();
            }
            log.info("总数: {}", jsonObj.getInteger("count"));
//            System.out.println("searchKDJStocks jsonObj: " + jsonObj);

            // 获取data数组
            JSONArray dataArr = jsonObj.getJSONArray("data");
//            System.out.println("jsonObj=:" + jsonObj);
            Map<String, Stock> stocks = new HashMap<>();

            for (int i = 0; i < dataArr.size(); i++) {
                JSONObject stockJson = dataArr.getJSONObject(i);
//                System.out.println(stockJson.toJSONString());
                Stock stockMap = new Stock();
                stockMap.setCode(stockJson.getString("股票代码").substring(0, 6));
                stockMap.setName(stockJson.getString("股票简称"));
                stocks.put(stockMap.getCode(), stockMap);
            }
            System.out.println("stocks==" + stocks);
            return stocks;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("searchKDJStocks: {}", e.getMessage());
        }
        return new HashMap<>();
    }


}